package io.jboot.fly.utils;

import com.jfinal.plugin.activerecord.Page;
import io.jboot.Jboot;
import io.jboot.fly.model.EsConfig;
import io.jboot.fly.model.Post;
import io.jboot.utils.StringUtils;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.transport.client.PreBuiltTransportClient;

import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by admin on 2018/9/13.
 */
public class ElaticSearchUtils {

   public static  EsConfig config = Jboot.config(EsConfig.class);

    public static void createPostIndex(Post post) {
        try {
            TransportClient client=getClient();
            // 先构建client
            IndexResponse response = client.prepareIndex(config.getClusterIndex(), config.getClusterType(), post.getId())
                    .setSource(XContentFactory.jsonBuilder()
                            .startObject()
                            .field("title", post.getTitle())
                            .field("content",post.getContent())
                            .field("category_id", post.getCategoryId())
                            .field("user_id", post.getUserId())
                            .field("vote_up", post.getVoteUp())
                            .field("vote_down", post.getVoteDown())
//                            .field("price", post.getPrice())
                            .field("pay_point", post.getPayPoint())
                            .field("comment_count", post.getCommentCount())
                            .field("comment_time", DateTimeUtils.formatDateTime(post.getCommentTime()))
                            .field("view_count", post.getViewCount())
                            .field("created",post.getCreated().getTime())
                            .field("modified", DateTimeUtils.formatDateTime(post.getModified()))
                            .field("status", post.getStatus())
                            .field("userAttachment_id", post.getUserattachmentId())
                            .field("userAttachement_type", post.getUserattachementType())
                            .field("edit_mode", post.getEditMode())
                            .endObject())
                    .get();
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static TransportClient getClient() {
        try {
            Settings settings = Settings.builder()
                    .put("cluster.name", config.getClusterName())
                    .build();

            TransportClient client = new PreBuiltTransportClient(settings)
                    .addTransportAddress(new TransportAddress(InetAddress.getByName(config.getClusterIP()), config.getClusterPort()));
            return client;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    /**
     * 修改问题索引信息
     * @param post
     * @throws Exception
     */
    public static void updatePost(Post post) {
        try {
            TransportClient client=getClient();
            UpdateResponse response = client.prepareUpdate(config.getClusterIndex(), config.getClusterType(), post.getId())
                    .setDoc(XContentFactory.jsonBuilder()
                            .startObject()
                            .field("title", post.getTitle())
                            .field("content",post.getContent())
                            .field("category_id", post.getCategoryId())
                            .field("user_id", post.getUserId())
                            .field("vote_up", post.getVoteUp())
                            .field("vote_down", post.getVoteDown())
//                            .field("price", post.getPrice())
                            .field("pay_point", post.getPayPoint())
                            .field("comment_count", post.getCommentCount())
                            .field("comment_time", DateTimeUtils.formatDateTime(post.getCommentTime()))
                            .field("view_count", post.getViewCount())
                            .field("created",post.getCreated().getTime())
                            .field("modified", DateTimeUtils.formatDateTime(post.getModified()))
                            .field("status", post.getStatus())
                            .field("userAttachment_id", post.getUserattachmentId())
                            .field("userAttachement_type", post.getUserattachementType())
                            .field("edit_mode", post.getEditMode())
                            .endObject())
                    .get();
            System.out.println(response.getResult());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除 问答索引信息
     * @param post
     * @throws Exception
     */
    public static void deletePost(Post post)  {
        try {
            TransportClient client=getClient();
            DeleteResponse response = client.prepareDelete(config.getClusterIndex(), config.getClusterType(), post.getId()).get();
            System.out.println(response.getResult());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        searchPost(0,8,null,null,null,null, null);
    }

    /**
     * 获取问答信息
     * @param
     * @param userAttachementType
     * @throws Exception
     */
    public static Page<Post> searchPost(Integer pageNumber, Integer pageSize, String keyword, String type, String orderBy, Integer status, Integer userAttachementType) {
        try {
            TransportClient client=getClient();
            Page<Post> postPage=null;
            HighlightBuilder highlightBuilder = new HighlightBuilder().field("title").field("content");
            highlightBuilder.preTags("<span style=\"color:red\">");
            highlightBuilder.postTags("</span>");
            SearchResponse response=null;
            //如果关键词不为空
            if(!StringUtils.isBlank(keyword)){
                Integer statusVal=status==null?Post.STATUS_NORMAL:status;
                String orderByKey=orderBy==null?"created":orderBy;
                QueryBuilder queryBuilder=null;
                if(userAttachementType==null){
                    queryBuilder = QueryBuilders
                            .boolQuery()
                            .must(QueryBuilders.boolQuery()
                                    .should(QueryBuilders.matchPhraseQuery("title",keyword))
                                    .should(QueryBuilders.matchPhraseQuery("content",keyword)))
                            .must(QueryBuilders.matchQuery("category_id",type))
                            .must(QueryBuilders.matchQuery("status",statusVal));
                }else{
                    queryBuilder = QueryBuilders
                            .boolQuery()
                            .must(QueryBuilders.boolQuery()
                                    .should(QueryBuilders.matchPhraseQuery("title",keyword))
                                    .should(QueryBuilders.matchPhraseQuery("content",keyword)))
                            .must(QueryBuilders.matchQuery("category_id",type))
                            .must(QueryBuilders.matchQuery("status",statusVal))
                            .must(QueryBuilders.matchQuery("userAttachment_id",userAttachementType));
                }

                        response=client.prepareSearch(config.getClusterIndex())
                                .setTypes(config.getClusterType())
                                .setQuery(queryBuilder)
                                .addSort(orderByKey, SortOrder.DESC)
                                .setFrom((pageNumber-1)*pageSize)
                                .setSize(pageSize)
                                .highlighter(highlightBuilder)
                                .get();

            //如果不按关键词查询
            }else{
                //默认问题列表查询（状态、类型、创建时间倒序）
                Integer statusVal=status==null?Post.STATUS_NORMAL:status;
                String orderByKey=orderBy==null?"created":orderBy;
                QueryBuilder queryBuilder =null;
                if(userAttachementType==null){
                    queryBuilder= QueryBuilders
                            .boolQuery()
                            .must(QueryBuilders.matchQuery("category_id",type))
                            .must(QueryBuilders.matchQuery("status",statusVal));
                }else{
                    queryBuilder= QueryBuilders
                            .boolQuery()
                            .must(QueryBuilders.matchQuery("category_id",type))
                            .must(QueryBuilders.matchQuery("status",statusVal))
                            .must(QueryBuilders.matchQuery("userAttachment_id",userAttachementType));
                }


                response=client.prepareSearch(config.getClusterIndex())
                        .setTypes(config.getClusterType())
                        .setQuery(queryBuilder)
                        .addSort(orderByKey, SortOrder.DESC)
                        .setFrom((pageNumber-1)*pageSize)
                        .setSize(pageSize)
                        .get();

            }

            System.out.println(response.toString());
            Integer totalRow=Integer.parseInt(String.valueOf(response.getHits().totalHits));
            Integer totalPage=totalRow/pageSize+1;

            List<Post> postList=new ArrayList<>();
            //遍历结果
            for(SearchHit hit:response.getHits()){
                postList.add(hitsToPost(hit));
            }
            postPage=new Page(postList,pageNumber,pageSize,totalPage,totalRow);
            return postPage;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    private static Post hitsToPost(SearchHit hit) {
        Post post=new Post();
        List<Map<String,Object>> result = new ArrayList<>();
        Map<String, Object> source = hit.getSourceAsMap();
        //处理高亮片段
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        HighlightField nameField = highlightFields.get("title");
        if(nameField!=null){
            Text[] fragments = nameField.fragments();
            String nameTmp ="";
            for(Text text:fragments){
                nameTmp+=text;
            }
            //将高亮片段组装到结果中去
            post.setTitle(nameTmp);
        }else{
            post.setTitle((String) source.get("title"));
        }
        HighlightField contentField = highlightFields.get("content");
        if(contentField!=null){
            Text[] fragments = contentField.fragments();
            String nameTmp ="";
            for(Text text:fragments){
                nameTmp+=text;
            }
            //将高亮片段组装到结果中去
            post.setContent(nameTmp);
        }else{
            post.setContent((String) source.get("content"));
        }


        String category_id= (String) source.get("category_id");
        String user_id= (String) source.get("user_id");
        Long vote_up= Long.parseLong(source.get("vote_up")==null?"0":((Integer) source.get("vote_up")).toString());
        Long vote_down= Long.parseLong(source.get("vote_down")==null?"0":((Integer) source.get("vote_down")).toString());
//        BigDecimal price= (BigDecimal) source.get("price");
        Integer pay_point= (Integer) source.get("pay_point");
        Long comment_count= Long.parseLong(source.get("comment_count")==null?"0":((Integer) source.get("comment_count")).toString());
        Long view_count= Long.parseLong(source.get("view_count")==null?"0":((Integer) source.get("view_count")).toString());
        String userAttachement_type= (String) source.get("userAttachement_type");
        String userAttachment_id= (String) source.get("userAttachment_id");
        String edit_mode= (String) source.get("edit_mode");

        Date created=DateTimeUtils.parseStringToDate(DateUtils.secondToYYYYMMddHHmmss(source.get("created").toString()) ) ;
        Date modified=DateTimeUtils.parseStringToDate(source.get("modified").toString());
        Date comment_time=DateTimeUtils.parseStringToDate(source.get("comment_time").toString());

        post.setId(hit.getId());
        post.setCategoryId(category_id);
        post.setUserId(user_id);
        post.setVoteUp(vote_up);
        post.setVoteDown(vote_down);
//        post.setPrice(price);
        post.setPayPoint(pay_point);
        post.setCommentCount(comment_count);
        post.setViewCount(view_count);
        post.setCreated(created);
        post.setModified(modified);
        post.setCommentTime(comment_time);
        post.setUserattachementType(userAttachement_type);
        post.setUserattachmentId(userAttachment_id);
        post.setEditMode(edit_mode);


        return post;
    }

}
